<?php
/**
 * XmuSlh, web platform of Student Association Federation of Xiamen University
 * 
 * Rewritting one or some pages of StatusNet. 
 * To get the original version, please visit <http://status.net/>.
 * 
 * StatusNet, the distributed open-source microblogging tool
 * 
 * LICENCE: This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * This is a template class of the markup language outputter.
 * It is actually wrapped class of a XMLWriter.
 * 
 * 这是一个标记语言输出器的模板类, 它定义了一般类xml标记语言的输出方法.
 * 
 * @author		ytukie <ytukie@gmail.com>
 * @version		0.1
 * 
 */

// XmuSlh only.
if ( !defined('XMUSLH')) { exit(1); }

class XMLOutputter
{
	/**
	 * Wrapped XMLWriter object, which does most of the heavy lifing for 
	 * output.
	 */
	var $xw = null;
	
	/**
	 * Constructor.
	 * 
	 * Initializes the wrapped XMLWriter.
	 * 
	 * @param string	$output		URL for outputting, defaults to stdout.
	 * @param boolean	$indet		To indent output?
	 */
	function __construct($output = 'php://stdout', 
						 $indent = true)
	{
		$this->xw = new XMLWriter();
		$this->xw->openURI($output);
		// $this->xw->openURI('E:/Share/wwwroot/projects/i.xml');

// FIXME: indent might be designed to modified in the config.
		$this->xw->setIndent($indent);
		$this->xw->setIndentString('');
	}
	
	/**
	 * Start a new XML document.
	 * 
	 * @param string	$doc		document element.
	 * @param string	$public		public identifier.
	 * @param string	$system		system identifier.
	 * 
	 * @return void
	 */
	function startXML($doc = null, 
					  $public = null, 
					  $system = null)
	{
		$this->xw->startDocument('1.0', 'UTF-8');
		if ($doc) {
			$this->xw->writeDTD($doc, $public, $system);
		}
	}
	
	/**
	 * Finish an XML document.
	 * 
	 * It must be pairing appeared with startXML().
	 * 
	 * @return void
	 */	
	function endXML()
	{
		$this->xw->endDocument();
		$this->xw->flush();
	}
	
	/**
	 * Output an XML element.
	 * 
	 * Wrapped method to call a bunch of longer XMLWriter calls.
	 * 
	 * @param string	$tag		element type of tagname.
	 * @param array		$attrs		some attributes.
	 * @param string	$content	string content.
	 * 
	 * @return void
	 */
	function element($tag, 
					 $attrs = null, 
					 $content = null)
	{	
		$this->elementStart($tag, $attrs);
		if ( !is_null($content)) {
			$this->xw->text($content);
		}
		$this->elementEnd($tag);
	}
	
	/**
	 * Output a start tag for an element.
	 * 
	 * Mostly used for when an element has content that's
	 * not a simple string.
	 * 
	 * @param string	$tag		element type of tagname.
	 * @param array		$attrs		array of element attributes
	 * 
	 * @return void
	 */
	function elementStart($tag, 
						  $attrs = null)
	{
		$this->xw->startElement($tag);
        if (is_array($attrs)) {
            foreach ($attrs as $name => $value) {
                $this->xw->writeAttribute($name, $value);
            }
        } else if (is_string($attrs)) {
            $this->xw->writeAttribute('class', $attrs);
        }
	}
	
	/**
	 * Output an end tag for an element.
	 * 
	 * Used in conjunction with elementStart(). $tag param
	 * should match the elementStart() param.
	 * 
	 * @param string	$tag		element type or tagname
	 * 
	 * @return void
	 */
	function elementEnd($tag)
	{
// TODO: Check the extra single line tags.
// Check if to use if-else or increase effciency.
		static $singleline_tags = array('base', 'meta', 'link', 'hr',
                                  		'br', 'param', 'img', 'area',
                                  		'input', 'col');
		if (in_array($tag, $singleline_tags)) {
            $this->xw->endElement();
        } else {
            $this->xw->fullEndElement();
        }
	}
	
	/**
	 * Eliminated function text($xml).
	 */
	function text($txt)
	{
		$this->xw->text($txt);
	}
	
	/**
	 * Output raw xml.
	 */	
	function raw($content)
	{
		$this->xw->writeRaw($content);
	}
	
	/**
	 * Output a comment.
	 */
	function comment($comment)
	{
		$this->xw->writeComment($comment);
	}
}

?>